package com.geek.factory.service.scheduler;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.geek.factory.entity.InventoryDistribution;
import com.geek.factory.entity.Material;
import com.geek.factory.entity.Product;
import com.geek.factory.entity.StockWarning;
import com.geek.factory.service.IInventoryDistributionService;
import com.geek.factory.service.IMaterialService;
import com.geek.factory.service.IProductService;
import com.geek.factory.service.IStockWarningService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 库存预警定时任务
 */
@Component
@Slf4j
public class StockWarningScheduler {

    // 预警类型常量
    public static final String WARNING_TYPE_INSUFFICIENT = "insufficient"; // 库存不足
    public static final String WARNING_TYPE_EXCESS = "excess"; // 库存积压
    
    // 预警状态常量
    public static final String WARNING_STATUS_UNREAD = "unread"; // 未读
    public static final String WARNING_STATUS_READ = "read"; // 已读
    public static final String WARNING_STATUS_PROCESSED = "processed"; // 已处理

    @Autowired
    private IProductService productService;

    @Autowired
    private IMaterialService materialService;

    @Autowired
    private IInventoryDistributionService inventoryDistributionService;

    @Autowired
    private IStockWarningService stockWarningService;

    /**
     * 每天凌晨2点执行库存预警检查
     * 也可以根据需要调整为更频繁的检查
     */
    @Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
    @Async
    public void checkStockWarnings() {
        log.info("开始执行库存预警检查...");
        try {
            // 检查产品库存预警
            checkProductStockWarnings();
            
            // 检查原料库存预警
            checkMaterialStockWarnings();
            
            log.info("库存预警检查完成");
        } catch (Exception e) {
            log.error("执行库存预警检查时发生异常", e);
        }
    }

    /**
     * 检查产品库存预警
     */
    private void checkProductStockWarnings() {
        log.info("检查产品库存预警");
        
        // 1. 获取所有产品
        List<Product> products = productService.list();
        log.info("共有{}个产品需要检查库存预警", products.size());
        
        // 2. 逐个检查产品库存
        for (Product product : products) {
            // 只有设置了库存阈值的产品才需要检查
            if (product.getMinStock() == null && product.getMaxStock() == null) {
                continue;
            }
            
            // 3. 获取产品总库存
            BigDecimal totalStock = inventoryDistributionService.getTotalStockByProductId(product.getId());
            log.info("产品[{}]当前总库存: {}, 最小库存阈值: {}, 最大库存阈值: {}", 
                    product.getName(), totalStock, product.getMinStock(), product.getMaxStock());
            
            // 4. 检查是否低于最小库存
            if (product.getMinStock() != null && totalStock.compareTo(new BigDecimal(product.getMinStock())) < 0) {
                // 创建库存不足预警
                createStockWarning(
                    product.getId(), 
                    "product", 
                    product.getName(), 
                    product.getCode(), 
                    WARNING_TYPE_INSUFFICIENT,  // 使用常量
                    totalStock, 
                    new BigDecimal(product.getMinStock()),
                    null
                );
                log.info("产品[{}]库存不足预警已创建: 当前库存={}, 最小库存={}", 
                    product.getName(), totalStock, product.getMinStock());
            }
            
            // 5. 检查是否超过最大库存
            if (product.getMaxStock() != null && totalStock.compareTo(new BigDecimal(product.getMaxStock())) > 0) {
                // 创建库存积压预警
                createStockWarning(
                    product.getId(), 
                    "product", 
                    product.getName(), 
                    product.getCode(), 
                    WARNING_TYPE_EXCESS,  // 使用常量
                    totalStock, 
                    new BigDecimal(product.getMaxStock()),
                    null
                );
                log.info("产品[{}]库存积压预警已创建: 当前库存={}, 最大库存={}", 
                    product.getName(), totalStock, product.getMaxStock());
            }
        }
    }
    
    /**
     * 检查原料库存预警
     */
    private void checkMaterialStockWarnings() {
        log.info("检查原料库存预警");
        
        // 1. 获取所有原料
        List<Material> materials = materialService.list();
        log.info("共有{}个原料需要检查库存预警", materials.size());
        
        // 2. 逐个检查原料库存
        for (Material material : materials) {
            // 只有设置了库存阈值的原料才需要检查
            if (material.getMinStock() == null && material.getMaxStock() == null) {
                continue;
            }
            
            // 3. 获取原料总库存
            BigDecimal totalStock = inventoryDistributionService.getTotalStockByMaterialId(material.getMaterialId());
            log.info("原料[{}]当前总库存: {}, 最小库存阈值: {}, 最大库存阈值: {}", 
                    material.getMaterialName(), totalStock, material.getMinStock(), material.getMaxStock());
            
            // 4. 检查是否低于最小库存
            if (material.getMinStock() != null && totalStock.compareTo(new BigDecimal(material.getMinStock())) < 0) {
                // 创建库存不足预警
                createStockWarning(
                    material.getMaterialId(), 
                    "material", 
                    material.getMaterialName(), 
                    material.getMaterialCode(), 
                    WARNING_TYPE_INSUFFICIENT,  // 使用常量
                    totalStock, 
                    new BigDecimal(material.getMinStock()),
                    material.getUnit()
                );
                log.info("原料[{}]库存不足预警已创建: 当前库存={}, 最小库存={}", 
                    material.getMaterialName(), totalStock, material.getMinStock());
            }
            
            // 5. 检查是否超过最大库存
            if (material.getMaxStock() != null && totalStock.compareTo(new BigDecimal(material.getMaxStock())) > 0) {
                // 创建库存积压预警
                createStockWarning(
                    material.getMaterialId(), 
                    "material", 
                    material.getMaterialName(), 
                    material.getMaterialCode(), 
                    WARNING_TYPE_EXCESS,  // 使用常量
                    totalStock, 
                    new BigDecimal(material.getMaxStock()),
                    material.getUnit()
                );
                log.info("原料[{}]库存积压预警已创建: 当前库存={}, 最大库存={}", 
                    material.getMaterialName(), totalStock, material.getMaxStock());
            }
        }
    }
    
    /**
     * 创建库存预警记录
     */
    private void createStockWarning(
            Integer itemId, 
            String itemType, 
            String itemName, 
            String itemCode, 
            String warningType, 
            BigDecimal currentStock, 
            BigDecimal thresholdValue,
            String unit) {
            
        // 检查是否已存在未读的同类型预警
        LambdaQueryWrapper<StockWarning> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StockWarning::getItemId, itemId)
               .eq(StockWarning::getItemType, itemType)
               .eq(StockWarning::getWarningType, warningType)
               .eq(StockWarning::getStatus, WARNING_STATUS_UNREAD);  // 使用常量
               
        // 如果已存在未读预警，则不重复创建
        if (stockWarningService.count(wrapper) > 0) {
            log.info("已存在未读的{}类型预警，不重复创建", warningType);
            return;
        }
        
        // 创建新的预警记录
        StockWarning warning = new StockWarning();
        warning.setItemId(itemId);
        warning.setItemType(itemType);
        warning.setItemName(itemName);
        warning.setItemCode(itemCode != null ? itemCode : ""); // 确保itemCode不为null
        warning.setWarningType(warningType);
        warning.setCurrentStock(currentStock);
        warning.setThresholdValue(thresholdValue);
        warning.setUnit(unit);
        warning.setWarningTime(LocalDateTime.now());
        warning.setStatus(WARNING_STATUS_UNREAD);  // 使用常量
        
        // 保存预警记录
        stockWarningService.save(warning);
        log.info("创建{}类型预警: 物品[{}], ID={}, 当前库存={}, 阈值={}",
                warningType, itemName, itemId, currentStock, thresholdValue);
    }
    
    /**
     * 手动触发库存预警检查（用于测试）
     * @return 预警结果统计
     */
    public Map<String, Object> manualCheckStockWarnings() {
        log.info("手动触发库存预警检查");
        
        // 记录创建的预警数量
        Map<String, Integer> warningCounts = new HashMap<>();
        warningCounts.put("product_insufficient", 0);
        warningCounts.put("product_excess", 0);
        warningCounts.put("material_insufficient", 0);
        warningCounts.put("material_excess", 0);
        
        try {
            // 检查产品库存预警
            List<Product> products = productService.list();
            log.info("共有{}个产品需要检查库存预警", products.size());
            
            for (Product product : products) {
                // 只有设置了库存阈值的产品才需要检查
                if (product.getMinStock() == null && product.getMaxStock() == null) {
                    continue;
                }
                
                BigDecimal totalStock = inventoryDistributionService.getTotalStockByProductId(product.getId());
                
                // 检查是否低于最小库存
                if (product.getMinStock() != null && totalStock.compareTo(new BigDecimal(product.getMinStock())) < 0) {
                    createStockWarning(
                        product.getId(), 
                        "product", 
                        product.getName(), 
                        product.getCode(), 
                        WARNING_TYPE_INSUFFICIENT,
                        totalStock, 
                        new BigDecimal(product.getMinStock()),
                        null
                    );
                    warningCounts.put("product_insufficient", warningCounts.get("product_insufficient") + 1);
                }
                
                // 检查是否超过最大库存
                if (product.getMaxStock() != null && totalStock.compareTo(new BigDecimal(product.getMaxStock())) > 0) {
                    createStockWarning(
                        product.getId(), 
                        "product", 
                        product.getName(), 
                        product.getCode(), 
                        WARNING_TYPE_EXCESS,
                        totalStock, 
                        new BigDecimal(product.getMaxStock()),
                        null
                    );
                    warningCounts.put("product_excess", warningCounts.get("product_excess") + 1);
                }
            }
            
            // 检查原料库存预警
            List<Material> materials = materialService.list();
            log.info("共有{}个原料需要检查库存预警", materials.size());
            
            for (Material material : materials) {
                // 只有设置了库存阈值的原料才需要检查
                if (material.getMinStock() == null && material.getMaxStock() == null) {
                    continue;
                }
                
                BigDecimal totalStock = inventoryDistributionService.getTotalStockByMaterialId(material.getMaterialId());
                
                // 检查是否低于最小库存
                if (material.getMinStock() != null && totalStock.compareTo(new BigDecimal(material.getMinStock())) < 0) {
                    createStockWarning(
                        material.getMaterialId(), 
                        "material", 
                        material.getMaterialName(), 
                        material.getMaterialCode(), 
                        WARNING_TYPE_INSUFFICIENT,
                        totalStock, 
                        new BigDecimal(material.getMinStock()),
                        material.getUnit()
                    );
                    warningCounts.put("material_insufficient", warningCounts.get("material_insufficient") + 1);
                }
                
                // 检查是否超过最大库存
                if (material.getMaxStock() != null && totalStock.compareTo(new BigDecimal(material.getMaxStock())) > 0) {
                    createStockWarning(
                        material.getMaterialId(), 
                        "material", 
                        material.getMaterialName(), 
                        material.getMaterialCode(), 
                        WARNING_TYPE_EXCESS,
                        totalStock, 
                        new BigDecimal(material.getMaxStock()),
                        material.getUnit()
                    );
                    warningCounts.put("material_excess", warningCounts.get("material_excess") + 1);
                }
            }
            
        } catch (Exception e) {
            log.error("执行库存预警检查时发生异常", e);
        }
        
        // 统计总预警数
        int totalWarnings = warningCounts.values().stream().mapToInt(Integer::intValue).sum();
        
        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("totalWarnings", totalWarnings);
        result.put("warningCounts", warningCounts);
        result.put("timestamp", LocalDateTime.now());
        
        log.info("库存预警检查完成，共创建{}个预警", totalWarnings);
        return result;
    }
} 